package com.example.demo.test;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.util.HashMap;

/**
 * @ClassName linux_moniting_utils
 * @Description
 * @date 2022/12/19 13:34
 * @Author yanceysong
 * @Version 1.0
 */
public class linux_monitor implements monitor_inter, AutoCloseable {

    private final String ip;
    private final String username;
    private final String password;
    private final Connection connection;
    private Session session;

    public linux_monitor(String ip, String username, String password) {
        this.ip = ip;
        this.username = username;
        this.password = password;
        connection = login(ip, username, password);
    }

    public linux_monitor(String ip) {
        this.ip = ip;
        this.username = "root";
        this.password = "123000";
        connection = login(ip, username, password);
    }


    /**
     * 登录主机
     *
     * @return 登录成功返回true，否则返回false
     */
    private static Connection login(String ip, String username, String password) {
        boolean flg = false;
        Connection conn = null;
        try {
            conn = new Connection(ip);
            conn.connect();//连接
            flg = conn.authenticateWithPassword(username, password);//认证
            if (flg) {
                return conn;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return conn;
    }

    /**
     * 解析脚本执行返回的结果集
     *
     * @param in      输入流对象
     * @param charset 编码
     * @return 以纯文本的格式返回
     */
    private static String processStdout(InputStream in, String charset) {
        InputStream stdout = new StreamGobbler(in);
        StringBuilder buffer = new StringBuilder();
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(stdout, charset));
            String line = null;
            while ((line = br.readLine()) != null) {
                buffer.append(line).append("\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer.toString();
    }
//
//    public static void main(String[] args) throws InterruptedException, IOException {
//        long start = System.currentTimeMillis();
//        linux_monitor linux_monitor = new linux_monitor("172.21.1.189", "bugong", "Oraps123");
//        System.out.println(System.currentTimeMillis() - start);
//        start = System.currentTimeMillis();
//        System.out.println(linux_monitor.get_cpu_core_numbers());
//        System.out.println(linux_monitor.get_cpu_used());
//        System.out.println(linux_monitor.get_mem());
//        System.out.println(linux_monitor.get_disk());
//        System.out.println(System.currentTimeMillis() - start);
//        start = System.currentTimeMillis();
//        System.out.println(linux_monitor.get_all());
//        System.out.println(System.currentTimeMillis() - start);
//        linux_monitor.close();
//    }

    /**
     * 字节数自动转对应的单位
     *
     * @param size 字节数
     * @return 转好的最大单位
     */
    private static String kb_format(long size) {
        StringBuilder bytes = new StringBuilder();
        DecimalFormat format = new DecimalFormat("###.0");
        if (size >= 1024 * 1024) {
            double i = (size / (1024.0 * 1024.0));
            bytes.append(format.format(i)).append("GB");
        } else if (size >= 1024) {
            double i = size / 1024.0;
            bytes.append(format.format(i)).append("MB");
        } else {
            bytes.append(format.format(size)).append("KB");
        }
        return bytes.toString();
    }



    /**
     * 获取所有的监控信息
     *
     * @return 结果
     */
    public HashMap<String, String> get_all() {
        HashMap<String, String> result_map = new HashMap<>();
        String result = execute(metrics_const.GET_DISK_COMMAND + "&&" + metrics_const.GET_CPU_USED_COMMAND + "&&" + metrics_const.GET_MEM_COMMAND);
        try {
            String[] all_raw = result.split("\n");
            String disk_raw = all_raw[0];
            String cpu_raw = all_raw[1];
            String mem_raw = all_raw[2];
            result_map.put(metrics_const.MONITOR_ITEM_CPU, get_cpu_used(cpu_raw));
            String[] mem_raw_result = mem_raw.split(" ");
            String mem_total = mem_raw_result[0];
            String mem_avl = mem_raw_result[1];
            result_map.put(metrics_const.MONITOR_ITEM_MEM, kb_format(Long.parseLong(mem_total) - Long.parseLong(mem_avl)) + "/" + kb_format(Long.parseLong(mem_total)));
            String[] disk_raw_result = disk_raw.split(" ");
            String total = disk_raw_result[0];
            String used = disk_raw_result[1];
            result_map.put(metrics_const.MONITOR_ITEM_DISK, kb_format(Long.parseLong(used)) + "/" + kb_format(Long.parseLong(total)));
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(result);
        }
        return result_map;
    }

    /**
     * 获取cpu的使用率
     *
     * @return 结果
     */
    public String get_cpu_used() {
        String result = execute(metrics_const.GET_CPU_USED_COMMAND).trim();
        String[] cpu_raw = result.split(" ");
        float sum = 0;
        for (String item : cpu_raw) {
            sum += Float.parseFloat(item);
        }
        DecimalFormat df = new DecimalFormat("0.0");
        df.setRoundingMode(RoundingMode.HALF_UP);
        return Double.parseDouble(df.format(sum)) + "%";
    }

    private String get_cpu_used(String cpu_result) {
        String[] cpu_raw = cpu_result.split(" ");
        float sum = 0;
        for (String item : cpu_raw) {
            sum += Float.parseFloat(item);
        }
        DecimalFormat df = new DecimalFormat("0.0");
        df.setRoundingMode(RoundingMode.HALF_UP);
        return Double.parseDouble(df.format(sum)) + "%";
    }

    /**
     * 获取服务器的内存使用
     *
     * @return 内存使用情况
     */
    public String get_mem() {
        String result = execute(metrics_const.GET_MEM_COMMAND);
        String[] mem_raw = result.split(" ");
        String total = mem_raw[0];
        String avl = mem_raw[1];
        return kb_format(Long.parseLong(total) - Long.parseLong(avl)) + "/" + kb_format(Long.parseLong(total));
    }

    /**
     * 远程执行shell脚本或者命令
     *
     * @param cmd 即将执行的命令
     * @return 命令执行完后返回的结果值
     */
    private String execute(String cmd) {
        String result = null;
        try {
            session = null;
            session = connection.openSession();
            session.execCommand(cmd);//执行命令
            result = processStdout(session.getStdout(), StandardCharsets.UTF_8.name());
            //如果为得到标准输出为空，说明脚本执行出错了
            if (result.equals("")) {
                result = processStdout(session.getStderr(), StandardCharsets.UTF_8.name());
            }
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
            monitor_client_factory.close(ip);
        }
        return result != null ? result.trim() : null;
    }

    /**
     * 获取服务器的磁盘信息
     *
     * @return 磁盘信息
     */
    public String get_disk() {
        String result = execute(metrics_const.GET_DISK_COMMAND);
        String[] disk_raw = result.split(" ");
        String total = disk_raw[0];
        String used = disk_raw[1];
        return kb_format(Long.parseLong(used)) + "/" + kb_format(Long.parseLong(total));
    }

    /**
     * 获取CPU的核心数量
     *
     * @return 核心数量
     */
    public String get_cpu_core_numbers() {
        return execute(metrics_const.GET_CPU_CORE_NUMBERS_COMMAND);
    }

    /**
     * 关闭连接
     */
    public void close() {
        try {
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
